package cn.jhz.learn.community_dynamic.app.controller;

import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Optional;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import com.fasterxml.jackson.databind.ObjectMapper;

import cn.jhz.learn.community_dynamic.common.bean.JsonData;
import cn.jhz.learn.community_dynamic.manager.MsgManager;
import cn.jhz.learn.community_dynamic.manager.WebSocketManager;
import cn.jhz.learn.community_dynamic.model.UserEntity;
import cn.jhz.learn.community_dynamic.security.helper.LoginHelper;
import cn.jhz.learn.community_dynamic.vo.app.MsgView;

@RestController
@RequestMapping("api/")
public class MsgController {
    private final MsgManager msgManager;
    private final WebSocketManager webSoketManager;
    private final ObjectMapper objectMapper;
    
    @Autowired
    public MsgController(MsgManager msgManager, WebSocketManager webSoketManager, ObjectMapper objectMapper) {
	super();
	this.msgManager = msgManager;
	this.webSoketManager = webSoketManager;
	this.objectMapper = objectMapper;
    }

    @GetMapping("auth/chat/get")
    @PreAuthorize("hasAuthority('chat::get')")
    public JsonData getQueue() {
	return JsonData.newSuccessInstance(this.msgManager.getInstance(String.valueOf(((UserEntity)LoginHelper.getLoginUser().get()).getLoginId())).orElse(new ArrayDeque<>()));
    }
    
    @PostMapping("auth/chat/send")
    @PreAuthorize("hasAuthority('chat::send')")
    public JsonData sendMsg(@RequestBody MsgView view) throws IOException {
	String targetId = view.getToId();
	view.setToId(null);
	view.setFromId(String.valueOf(((UserEntity)LoginHelper.getLoginUser().get()).getLoginId()));
	Optional<WebSocketSession> sessionOptional = webSoketManager.getInstance(targetId);
	if(sessionOptional.isPresent()) {
	    sessionOptional.get().sendMessage(new TextMessage(objectMapper.writeValueAsString(view)));
	} else {
	    Optional<Queue<MsgView>> queueOptional = this.msgManager.getInstance(targetId);
	    if(queueOptional.isPresent()) {
		queueOptional.get().offer(view);
		this.msgManager.putInstance(targetId, queueOptional.get());
	    } else {
		Queue<MsgView> queue = queueOptional.orElseGet(ConcurrentLinkedQueue::new);
		queueOptional.get().offer(view);
		this.msgManager.cacheInstance(targetId, queue);
	    }
	}
	return JsonData.newSuccessInstance();
    }
}
